Persistence是一个支持多数据源,O-R映射和SQL映射且简单易用的持久化框架。 最新版本可以满足复杂应用程序开发的需要。 它将帮助开发人员减少花在DAO模块上的开发和维护时间。
新版本的日志工具根据Persistence2.0的需求做了改进,主要特点是:
配置文件内容如下:
//show welcome words welcome=false //print in console debug=true //log folder path logFolderPath=D:/log/ //custom date format //dateFormat=yyyy-MM-dd HH:mm:ss:SSS //log info in single line singleLineLog=true //the min level to show log in console //leve:fatal > error > warn > info > debug minLevel2Print=info //the min level to record log in file minLevel2File=warn
调用方法如下:
Logger logger = Logger.getInstance();
//simple model, no exception
logger.debug("[Test]" + info, null);
//simple model, has an exception
logger.error("[Test]" + info, new Exception("Error."));
//detail model, has an exception
LogData data = new LogData();
data.setUser("admin:tom") //Not necessary
.setSource("login.jsp") //Not necessary
.setCategory("security") //Not necessary
.setData("User name : tom . ") //Not necessary
.setDescription("Login error."); //Not necessary
logger.fatal(data, new Exception("Error."));
数据源工具根据Persistence2.0的需求做了改进,主要变化是使用ThreadLocal管理线程。
连接池配置
<?xml version='1.0' encoding='UTF-8'?>
<Context>
<DataSource name="mysql" type="javax.sql.DataSource">
<parameter>
<name>driverClass</name>
<value>com.mysql.jdbc.Driver</value>
</parameter>
<parameter>
<name>url</name>
<value>jdbc:mysql://localhost:3306/platform</value>
</parameter>
<parameter>
<name>user</name>
<value>root</value>
</parameter>
<parameter>
<name>pwd</name>
<value></value>
</parameter>
<parameter>
<name>associateConnectionPool</name>
<value>true</value>
</parameter>
<parameter>
<name>connectionPoolName</name>
<value>mysqlpool</value>
</parameter>
</DataSource>
<ConnectionPoolConfig name="mysqlpool">
<parameter>
<name>maxStatements</name>
<value>20</value>
</parameter>
<parameter>
<name>initialPoolSize</name>
<value>10</value>
</parameter>
<parameter>
<name>minPoolSize</name>
<value>10</value>
</parameter>
<parameter>
<name>maxPoolSize</name>
<value>20</value>
</parameter>
<parameter>
<name>maxidleTime</name>
<value>3</value>
</parameter>
<parameter>
<name>propertyCycle</name>
<value>300</value>
</parameter>
</ConnectionPoolConfig>
</Context>
调用代码
//The default datasource of Persistence2 framework is the first datasource in xml String defaultDataSourceName = MultiConnectionPool.getInstance().getDefaultDataSourceName(); //Get connection from connection pool of default datasource Connection conn1 = MultiConnectionPool.getInstance().getConnection(defaultDataSourceName); // Get connection from connection pool by datasource name Connection conn2 = MultiConnectionPool.getInstance().getConnection(“test”);
ORM规则的控制粒度是表级(或对象级),用于在表和对象之间建立映射关系,实现对单表数据的快速存取。其特点是配置简单,但表的字段和对象的属性的名称需一致,模式单一,适用于完整对象的存取。
<?xml version="1.0" encoding="UTF-8"?> <config> <object-sql-mapping> <object> >class>com.nonesole.web.platform.sys.User>/class> <table>sys_user </table> <primery-key>id</primery-key> </object> <object> <class>com.nonesole.web.platform.sys.Role>/class> <table>sys_role</table> <primery-key>id</primery-key> </object> <object> <class>com.nonesole.web.platform.sys.UserRole>/class> <table>sys_user_role</table> <primery-key/> </object> </object-sql-mapping> </config>
配置说明:
ORM-PLUS规则的控制粒度是字段级(或属性级),基于ORM规则基础上,用于在表字段和对象的属性之间建立映射关系,字段名与属性名需一致。该规则的特点是控制灵活,但配置复杂。
<?xml version="1.0" encoding="UTF-8"?> <config> <actions> <action name="findUserById" transaction="true"> <orm-action>select</orm-action> <input> <object property="orm-pojo"> <mapping> <source> <where>true</where> <name>id</name> <class>int</class> <not-null>true</not-null> </source> <target/> </mapping> </object> </input> <output> <object property="pojo-list"> <object-class>java.util.ArrayList</object-class> <item-class>com.nonesole.web.platform.sys.User </item-class> <mapping> <source> <name>name</name> </source> <target> <name>name</name> <class>String</class> </target> </mapping> </object> </output> </action> </actions> </config>
配置说明:
SQL-MAPPING规则的控制粒度是字段级(或属性级),与ORM-PLUS规则的最大不同之处在于,SQL-MAPPING规则在SQL字段和对象的属性之间建立映射关系,与表无关,字段名与属性名无需一致。该规则的特点是控制灵活,接口丰富,但配置复杂。
<?xml version="1.0" encoding="UTF-8"?> <config> <actions> <action name="findUsersByAge" transaction="true"> <input> <object property="map"> <mapping> <source> <name>age</name> <class>int</class> <not-null>true</not-null> </source> <target> <name>//age</name> </target> </mapping> </object> </input> <output> <object property="pojo-list"> <object-class>java.util.ArrayList</object-class> <item-class>com.nonesole.web.platform.sys.User </item-class> <mapping> <source> <name>name</name> </source> <target> <name>name</name> <class>String</class> </target> </mapping> </object> </output> <sql>select * from user where age>//age</sql> </action> </actions> </config>
配置说明:(与ORM-PLUS重复的不再赘述)
保存整个对象的实现很简单,只需按照ORM规则设置好映射关系,调用过程由框架全权处理。
配置示例(如果无主键primery-key可以为空):
<?xml version="1.0" encoding="UTF-8"?> <config> <object-sql-mapping> <object> <class>com.nonesole.web.platform.sys.User</class> <table>sys_users </table> <primery-key>id</primery-key> </object> </object-sql-mapping> </config>
代码示例:
User u = new User();
u.setName("tom");
……
IOrmAction action = PersistenceFactory.getInstance().getOrmAction();
action.insert(u);
System.out.println(u.getId());
批量保存的配置与单个保存一致,不再赘述。代码如下:
List<User> users = new ArrayList<User>(); users.add(…); IOrmAction action = PersistenceFactory.getInstance().getOrmAction(); action. action.batchInsert(users);
针对当前需求,最佳方案是依托 ORM-PLUS规则实现。
配置示例:
<?xml version="1.0" encoding="UTF-8"?> <config> <actions> <action name="saveUser" transaction="true"> <orm-action>insert</orm-action> <input> <object property="orm-pojo"> <mapping> <source> <name>name</name> <class>java.lang.String</class> <not-null>true</not-null> <default-value/> <min-length>2</min-length> <max-length>20</max-length> </source> <target/> </mapping> </object> </input> <output></output> </action> </actions> </config>
代码示例:
User u = new User();
u.setName("tom");
……
IOrmPlusAction action = PersistenceFactory.getInstance().getOrmPlusAction();
action.doAction("saveUser", u);
System.out.println(u.getId());
配置示例:
<?xml version="1.0" encoding="UTF-8"?> <config> <actions> <action name="batchSaveUser" transaction="true"> <orm-action>insert</orm-action> <input> <object property="orm-pojo-list"> <mapping> <source> <name>name</name> <class>java.lang.String</class> <not-null>true</not-null> <min-length>2</min-length> <max-length>20</max-length> </source> <target/> </mapping> </object> </input> <output></output> </action> </actions> </config>
代码示例:
List<User> users = new ArrayList<User>();
users.add(…);
IOrmPlusAction action = PersistenceFactory.getInstance().getOrmPlusAction();
action.doAction("batchSaveUser ", users);
在某些特定场景下,开发者仅仅需要一个可调用SQL的方法,没有输入和输出。例如执行insert…select语句。
使用SQL-MAPPING实现
配置示例:
<config> <actions> <action name="createTempTable" transaction="true"> <input/> <output/> <sql>insert into temp(id,name) select id,name from user</sql> </action> </actions> </config>
代码示例:
IVoidAction action = PersistenceFactory.getInstance().getVoidAction();
action.doAction("createTempTable", null);
使用ORM实现
代码示例:
IOrmAction action = PersistenceFactory.getInstance().getOrmAction();
action.execute("insert into temp(id,name) select id,name from user");
当前需求场景,只需按照ORM规则设置好映射关系,调用过程由框架全权处理。需要注意的是,主键一定不能为空。
配置示例(主键primery-key不可以为空):
<?xml version="1.0" encoding="UTF-8"?> <config> <object-sql-mapping> <object> <class>com.nonesole.web.platform.sys. User</class> <table>sys_users</table> <primery-key>id</primery-key> </object> </object-sql-mapping> </config>
代码示例:
User u = new User();
u.setId(10);
u.setName("tom");
……
IOrmAction action = PersistenceFactory.getInstance().getOrmAction();
action.update(u);
批量修改的配置与单个修改一致,不再赘述。代码如下:
List<User> users = new ArrayList<User>(); users.add(…); IOrmAction action = PersistenceFactory.getInstance().getOrmAction(); action. action.batchUpdate(users);
通过ORM-PLUS规则来实现数据的修改,重点是where子句的配置。
配置示例:
<?xml version="1.0" encoding="UTF-8"?> <config> <actions> <action name="updateUser" transaction="true"> <orm-action>update</orm-action> <input> <object property="orm-pojo"> <mapping> <source> <where>true</where> <name>id</name> <class>int</class> <not-null>true</not-null> </source> <target/> </mapping> <mapping> <source> <name>name</name> <class>java.lang.String</class> <not-null>true</not-null> </source> <target/> </mapping> </object> </input> <output></output> </action> </actions> </config>
代码示例:
User u = new User();
u.setId(8);
u.setName("tom");
IOrmPlusAction action = PersistenceFactory.getInstance().getOrmPlusAction();
action.doAction("updateUser", u);
配置示例:
<?xml version="1.0" encoding="UTF-8"?> <config> <actions> <action name="updateUser" transaction="true"> <input> <object property="map"> <mapping> <source> <name>id</name> <class>int</class> </source> <target> <name>//id</name> </target> </mapping> <mapping> <source> <name>name</name> <class>String</class> </source> <target> <name>//name</name> </target> </mapping> </object> </input> <output></output> <sql> update user set name=//name where id=//id and not exist (select 1 from (select 1 from user_role where user_id=//id) t1 ) </sql> </action> </actions> </config>
代码示例:
Map map = new HashMap();
map.put("id",10);
map.put("name","tom");
……
IVoidAction action = PersistenceFactory.getInstance().getVoidAction();
action.doAction("updateUser ", map);
配置示例(主键primery-key不可以为空):
<?xml version="1.0" encoding="UTF-8"?> <config> <object-sql-mapping> <object> <class>com.nonesole.web.platform.sys.user.User</class> <table>sys_users_login</table> <primery-key>id</primery-key> </object> </object-sql-mapping> </config>
代码示例:
User u = new User(); u.setId(10); …… IOrmAction action = PersistenceFactory.getInstance().getOrmAction(); action.delete(u);
批量删除的配置与单个对象的删除一致,不再赘述。代码如下:
List<User> users = new ArrayList<User>(); users.add(…); IOrmAction action = PersistenceFactory.getInstance().getOrmAction(); action. action.batchDelete(users);
ORM-PLUS方法
配置示例:
<?xml version="1.0" encoding="UTF-8"?> <config> <actions> <action name="deleteUser" transaction="true"> <orm-action>delete</orm-action> <input> <object property="orm-pojo"> <mapping> <source> <where>true</where> <name>id</name> <class>int</class> <not-null>true</not-null> </source> <target/> </mapping> <mapping> <source> <where>true</where> <name>name</name> <class>java.lang.String</class> <not-null>true</not-null> </source> <target/> </mapping> </object> </input> <output></output> </action> </actions> </config>
代码示例:
User u = new User();
u.setName("tom");
……
IOrmPlusAction action = PersistenceFactory.getInstance().getOrmPlusAction();
action.doAction("updateUser", u);
SQL-MAPPING方法
针对级联删除,框架提供了SQL-MAPPING规则来实现。
配置示例(针对级联删除操作这样需要执行多个SQL的场景,框架允许在一个Action中配置多个<sql>标签。):
<?xml version="1.0" encoding="UTF-8"?> <config> <actions> <action name="deleteUser" transaction="true"> <input> <object property="map"> <mapping> <source> <name>id</name> <class>int</class> </source> <target> <name>//id</name> </target> </mapping> </object> </input> <output></output> <sql>delete from user_role where user_id=//id</sql> <sql>delete from user where id=//id </sql> </action> </actions> </config>
代码示例:
Map map = new HashMap();
map.put("id",10);
……
IVoidAction action = PersistenceFactory.getInstance().getVoidAction();
action.doAction("updateUser ", map);
ORM方法
基于ORM规则的DQL与DML的持久化配置无差别,这里不再赘述。
代码示例:
IOrmAction action = PersistenceFactory.getInstance().getOrmAction();
List<Object> users = action.execute("select * from user",User.class);
ORM-PLUS方法
配置示例:
<action name="findUsers" transaction="true"> <orm-action>select</orm-action> <input></input> <output> <object property="pojo-list"> <object-class>java.util.ArrayList</object-class> <item-class>com.nonesole.User</item-class> <mapping> <source> <name>name</name> </source> <target> <name>name</name> <class>String</class> </target> </mapping> </object> </output> </action>
代码示例:
IOrmPlusAction action =
PersistenceFactory.getInstance().getOrmPlusAction();
List<Object> users = action. doQueryAction ("findUsers ", new User());
SQL-MAPPING方法
配置示例:
<?xml version="1.0" encoding="UTF-8"?> <config> <actions> <action name="findUsers" transaction="true"> <input></input> <output> <object property="pojo-list"> <object-class>java.util.ArrayList</object-class> <item-class>com.nonesole.User</item-class> <mapping> <source> <name>name</name> </source> <target> <name>name</name> <class>String</class> </target> </mapping> </object> </output> <sql>select * from user</sql> </action> </actions> </config>
代码示例:
IPojoAction<User> action =
PersistenceFactory.getInstance().getPojoAction();
List<User> users = action. pojoListAction ("findUsers", null);
ORM方法
此场景下,SQL中需要编入外部数据,如果使用ORM接口,就需要拼SQL,从安全的角度,不建议使用。
ORM-PLUS方法
配置示例:
<action name="findUsers" transaction="true"> <orm-action>select</orm-action> <input> <object property="orm-pojo"> <mapping> <source> <where>true</where> <name>id</name> <class>int</class> <not-null>true</not-null> </source> <target/> </mapping> </object> </input> <output> <object property="pojo-list"> <object-class>java.util.ArrayList</object-class> <item-class>com.nonesole.User</item-class> <mapping> <source> <name>name</name> </source> <target> <name>name</name> <class>String</class> </target> </mapping> </object> </output> </action>
代码示例:
User user = new User();
user.setAge(18);
IOrmPlusAction action = PersistenceFactory.getInstance().getOrmPlusAction();
List<User> users = action. doQueryAction ("findUsers ", user);
SQL-MAPPING方法
配置示例:
<action name="findUsers" transaction="true"> <input> <object property="map"> <mapping> <source> <name>age</name> <class>int</class> <not-null>true</not-null> </source> <target> <name>//age</name> </target> </mapping> </object> </input> <output> <object property="pojo-list"> <object-class>java.util.ArrayList</object-class> <item-class>com.nonesole.User</item-class> <mapping> <source> <name>name</name> </source> <target> <name>name</name> <class>String</class> </target> </mapping> </object> </output> <sql>select * from user where age=//age</sql> </action>
代码示例:
Map<String,Object> map = new HashMap<String,Object>();
map.put("age",18);
IPojoAction<User> action =
PersistenceFactory.getInstance().getPojoAction();
List<User> users = action. pojoListAction ("findUsers", map);
面对复杂的业务查询,框架提供了2种解决方案,从安全性角度来说,推荐使用预编译方案,带来的是配置和编码复杂度的提升。从易用性角度出发,非预编译方案更受欢迎。
预编译解决方案
配置示例:
<action name="findUsers" transaction="true"> <input> <object property="map"> <mapping> <source> <name>start_index</name> <class>int</class> <not-null>true</not-null> <default-value>1</default-value> </source> <target> <name>//start_index</name> </target> </mapping> <mapping> <source> <name>condition</name> <class>java.lang.String</class> <not-null>false</not-null> </source> <target> <name>//condition</name> </target> <sql-part>true</sql-part> </mapping> </object> </input> <output> <object property="pojo-list"> <object-class>java.util.ArrayList</object-class> <item-class>com.nonesole.User</item-class> <mapping> <source> <name>name</name> </source> <target> <name>name</name> <class>java.lang.String</class> </target> </mapping> </object> </output> <sql> select * from sys_users_login //condition order by id desc limit //start_index,10 </sql> </action>
配置说明:
1.依据SQL-MAPPING规则,框架先对SQL进行编译处理,再向SQL赋值。
2.以当前场景为例,动态拼接后的提交框架处理的数据如下:
//condition= where (name like //name// and nick_name like //name//)
//name//=%tom%
start_index=1
框架将先将//condition与<sql>标签中的内容拼成完整SQL,编译之后再将name和start_index的数据编入SQL,并执行。
代码示例:
Map<String,Object> map = new HashMap<String,Object>();
map.put("start_index ",1);
map.put("//condition", "where (name like //name// and nick_name like //name//)");
map.put("//name//","%tom%");
IPojoAction<User> action =
PersistenceFactory.getInstance().getPojoAction();
List<User> users = action. pojoListAction ("findUsers", map);
ORM方案(非预编译)
该方案无需配置,直接在代码中拼SQL即可,但返回值类型受限。
代码示例:
String sql = "select * from user where age > " + 18; IOrmAction action = PersistenceFactory.getInstance().getOrmAction(); List<Object> users = action.execute(sql,User.class);
SQL-MAPPING方案(非预编译)
该方案的返回值类型可选,但还是要在代码中拼SQL,传入数据的安全性和正确性需要开发者自行保障。
配置示例:
<action name="findUsers" transaction="true"> <input> <object property="map"> <mapping> <source> <name>condition</name> <class>java.lang.String</class> <not-null>false</not-null> </source> <target> <name>//condition</name> </target> </mapping> </object> </input> <output> <object property="simple-list"> <mapping> <source> <name>id</name> </source> <target> <class>int</class> </target> </mapping> </object> </output> <sql>select id from sys_users_login //condition order by id desc</sql> </action>
代码示例1:
Map<String,Object> map = new HashMap<String,Object>();
map.put("condition", "where age > 18");
Connection conn = PersistenceFactory.getInstance().getDefaultConnection();
IArrayValueAction action = PersistenceFactory.getInstance().getArrayValueAction();
//It is not prepared statement
Integer[] id = action. intArrayAction ("findUser", map, conn, false);
代码示例2:
Map<String,Object> map = new HashMap<String,Object>();
map.put("condition", "where age > 18");
Connection conn = PersistenceFactory.getInstance().getDefaultConnection();
IListValueAction action = PersistenceFactory.getInstance().getListValueAction ();
//It is not prepared statement
List<Integer> id = action. intListAction ("findUser", map, conn, false);
配置示例:
<action name="deleteUser" transaction="true"> …… <sql>delete from user_role where user_id=//id</sql> <sql>delete from user where id=//id</sql> <sql>insert into log(…) values(…)</sql> </action>
代码示例:
Map<String,Object> map = new HashMap<String,Object>();
map.put("id", 10);
……
IVoidAction action = PersistenceFactory.getInstance().getVoidAction();
action.doAction("deleteUser", map);
配置示例:
<action name="deleteUserRelation" transaction="false"> …… <sql>delete from user_role where user_id=//id</sql> </action> <object-sql-mapping> <object> <class>com.nonesole.web.platform.sys.User</class> <table>sys_users </table> <primery-key>id</primery-key> </object> <object> <class>com.nonesole.web.platform.sys.Log</class> <table>sys_log</table> <primery-key>id</primery-key> </object> </object-sql-mapping>
代码示例:
PSession ps = new PSession();
Map<String,Object> map = new HashMap<String,Object>();
……
ps.voidAction("deleteUserRelation", map);
User u = new User();
u.setId(10);
ps.delete(u);
Log log = new Log();
log.setText("error.");
ps.insert(log);
ps.commit();